#include "Precompiled.h"
#include "ImGuiLua.h"

#ifdef BIND_IMGUI_LUA
#include <sol/sol.hpp>
#include <imgui/imgui.h>

namespace Lumos
{
    void BindImGuiLua(sol::state& solState)
    {
        // imgui bindings=
        sol::table globals = solState.globals();
        sol::table imgui   = solState.create_table();
        globals["gui"]     = imgui;

        imgui.new_enum("DrawCornerFlags",
                       "TopLeft",
                       1 << 0,
                       "TopRight",
                       1 << 1,
                       "BotLeft",
                       1 << 2,
                       "BotRight",
                       1 << 3,
                       "Top",
                       ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
                       "Bot",
                       ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
                       "Left",
                       ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomLeft,
                       "Right",
                       ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight,
                       "All",
                       0xF);

        imgui.new_enum("DrawListFlags", "None", 0, "AntiAliasedLines", 1 << 0, "AntiAliasedFill", 1 << 1);

        imgui.new_enum("FontAtlasFlags", "None", 0, "NoPowerOfTwoHeight", 1 << 0, "NoMouseCursors", 1 << 1);

        imgui.new_enum(
            "BackendFlags", "None", 0, "HasGamepad", 1 << 0, "HasMouseCursors", 1 << 1, "HasSetMousePos", 1 << 2);

        imgui.new_enum("Col",
                       "Text",
                       0,
                       "TextDisabled",
                       1,
                       "WindowBg",
                       2,
                       "ChildBg",
                       3,
                       "PopupBg",
                       4,
                       "Border",
                       5,
                       "BorderShadow",
                       6,
                       "FrameBg",
                       7,
                       "FrameBgHovered",
                       8,
                       "FrameBgActive",
                       9,
                       "TitleBg",
                       10,
                       "TitleBgActive",
                       11,
                       "TitleBgCollapsed",
                       12,
                       "MenuBarBg",
                       13,
                       "ScrollbarBg",
                       14,
                       "ScrollbarGrab",
                       15,
                       "ScrollbarGrabHovered",
                       16,
                       "ScrollbarGrabActive",
                       17,
                       "CheckMark",
                       18,
                       "SliderGrab",
                       19,
                       "SliderGrabActive",
                       20,
                       "Button",
                       21,
                       "ButtonHovered",
                       22,
                       "ButtonActive",
                       23,
                       "Header",
                       24,
                       "HeaderHovered",
                       25,
                       "HeaderActive",
                       26,
                       "Separator",
                       27,
                       "SeparatorHovered",
                       28,
                       "SeparatorActive",
                       29,
                       "ResizeGrip",
                       30,
                       "ResizeGripHovered",
                       31,
                       "ResizeGripActive",
                       32,
                       "Tab",
                       33,
                       "TabHovered",
                       34,
                       "TabActive",
                       35,
                       "TabUnfocused",
                       36,
                       "TabUnfocusedActive",
                       37,
                       "PlotLines",
                       38,
                       "PlotLinesHovered",
                       39,
                       "PlotHistogram",
                       40,
                       "PlotHistogramHovered",
                       41,
                       "TextSelectedBg",
                       42,
                       "DragDropTarget",
                       43,
                       "NavHighlight",
                       44,
                       "NavWindowingHighlight",
                       45,
                       "NavWindowingDimBg",
                       46,
                       "ModalWindowDimBg",
                       47,
                       "COUNT",
                       48);

        imgui.new_enum("ColorEditFlags",
                       "None",
                       0,
                       "NoAlpha",
                       1 << 1,
                       "NoPicker",
                       1 << 2,
                       "NoOptions",
                       1 << 3,
                       "NoSmallPreview",
                       1 << 4,
                       "NoInputs",
                       1 << 5,
                       "NoTooltip",
                       1 << 6,
                       "NoLabel",
                       1 << 7,
                       "NoSidePreview",
                       1 << 8,
                       "NoDragDrop",
                       1 << 9,
                       "AlphaBar",
                       1 << 16,
                       "AlphaPreview",
                       1 << 17,
                       "AlphaPreviewHalf",
                       1 << 18,
                       "HDR",
                       1 << 19,
                       "RGB",
                       1 << 20,
                       "HSV",
                       1 << 21,
                       "HEX",
                       1 << 22,
                       "Uint8",
                       1 << 23,
                       "Float",
                       1 << 24,
                       "PickerHueBar",
                       1 << 25,
                       "PickerHueWheel",
                       1 << 26,
                       "_DataTypeMask",
                       ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,
                       "_PickerMask",
                       ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,
                       "_OptionsDefault",
                       ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueBar);

        imgui.new_enum("ComboFlags",
                       "None",
                       0,
                       "PopupAlignLeft",
                       1 << 0,
                       "HeightSmall",
                       1 << 1,
                       "HeightRegular",
                       1 << 2,
                       "HeightLarge",
                       1 << 3,
                       "HeightLargest",
                       1 << 4,
                       "NoArrowButton",
                       1 << 5,
                       "NoPreview",
                       1 << 6,
                       "HeightMask_",
                       ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge
                           | ImGuiComboFlags_HeightLargest);

        imgui.new_enum("Cond", "Always", 1 << 0, "Once", 1 << 1, "FirstUseEver", 1 << 2, "Appearing", 1 << 3);

        imgui.new_enum("ConfigFlags",
                       "None",
                       0,
                       "NavEnableKeyboard",
                       1 << 0,
                       "NavEnableGamepad",
                       1 << 1,
                       "NavEnableSetMousePos",
                       1 << 2,
                       "NavNoCaptureKeyboard",
                       1 << 3,
                       "NoMouse",
                       1 << 4,
                       "NoMouseCursorChange",
                       1 << 5,
                       "IsSRGB",
                       1 << 20,
                       "IsTouchScreen",
                       1 << 21);

        imgui.new_enum("DataType", "S32", 0, "U32", 1, "S64", 2, "U64", 3, "Float", 4, "Double", 5, "COUNT", 6);

        imgui.new_enum("Dir", "None", -1, "Left", 0, "Right", 1, "Up", 2, "Down", 3, "COUNT", 4);

        imgui.new_enum("DragDropFlags",
                       "None",
                       0,
                       "SourceNoPreviewTooltip",
                       1 << 0,
                       "SourceNoDisableHover",
                       1 << 1,
                       "SourceNoHoldToOpenOthers",
                       1 << 2,
                       "SourceAllowNullID",
                       1 << 3,
                       "SourceExtern",
                       1 << 4,
                       "SourceAutoExpirePayload",
                       1 << 5,
                       "AcceptBeforeDelivery",
                       1 << 10,
                       "AcceptNoDrawDefaultRect",
                       1 << 11,
                       "AcceptNoPreviewTooltip",
                       1 << 12,
                       "AcceptPeekOnly",
                       ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect);

        imgui.new_enum("FocusedFlags",
                       "None",
                       0,
                       "ChildWindows",
                       1 << 0,
                       "RootWindow",
                       1 << 1,
                       "AnyWindow",
                       1 << 2,
                       "RootAndChildWindows",
                       ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows);

        imgui.new_enum("HoveredFlags",
                       "None",
                       0,
                       "ChildWindows",
                       1 << 0,
                       "RootWindow",
                       1 << 1,
                       "AnyWindow",
                       1 << 2,
                       "AllowWhenBlockedByPopup",
                       1 << 3,
                       "AllowWhenBlockedByActiveItem",
                       1 << 5,
                       "AllowWhenOverlapped",
                       1 << 6,
                       "AllowWhenDisabled",
                       1 << 7,
                       "RectOnly",
                       ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
                           | ImGuiHoveredFlags_AllowWhenOverlapped,
                       "RootAndChildWindows",
                       ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows);

        imgui.new_enum("InputTextFlags",
                       "None",
                       0,
                       "CharsDecimal",
                       1 << 0,
                       "CharsHexadecimal",
                       1 << 1,
                       "CharsUppercase",
                       1 << 2,
                       "CharsNoBlank",
                       1 << 3,
                       "AutoSelectAll",
                       1 << 4,
                       "EnterReturnsTrue",
                       1 << 5,
                       "CallbackCompletion",
                       1 << 6,
                       "CallbackHistory",
                       1 << 7,
                       "CallbackAlways",
                       1 << 8,
                       "CallbackCharFilter",
                       1 << 9,
                       "AllowTabInput",
                       1 << 10,
                       "CtrlEnterForNewLine",
                       1 << 11,
                       "NoHorizontalScroll",
                       1 << 12,
                       "AlwaysInsertMode",
                       1 << 13,
                       "ReadOnly",
                       1 << 14,
                       "Password",
                       1 << 15,
                       "NoUndoRedo",
                       1 << 16,
                       "CharsScientific",
                       1 << 17,
                       "CallbackResize",
                       1 << 18,
                       "Multiline",
                       1 << 20);

        imgui.new_enum("Key",
                       "Tab",
                       0,
                       "LeftArrow",
                       1,
                       "RightArrow",
                       2,
                       "UpArrow",
                       3,
                       "DownArrow",
                       4,
                       "PageUp",
                       5,
                       "PageDown",
                       6,
                       "Home",
                       7,
                       "End",
                       8,
                       "Insert",
                       9,
                       "Delete",
                       10,
                       "Backspace",
                       11,
                       "Space",
                       12,
                       "Enter",
                       13,
                       "Escape",
                       14,
                       "A",
                       15,
                       "C",
                       16,
                       "V",
                       17,
                       "X",
                       18,
                       "Y",
                       19,
                       "Z",
                       20,
                       "COUNT",
                       21);

        imgui.new_enum("MouseCursor",
                       "None",
                       -1,
                       "Arrow",
                       0,
                       "TextInput",
                       1,
                       "ResizeAll",
                       2,
                       "ResizeNS",
                       3,
                       "ResizeEW",
                       4,
                       "ResizeNESW",
                       5,
                       "ResizeNWSE",
                       6,
                       "Hand",
                       7,
                       "COUNT",
                       8);

        imgui.new_enum("NavInput",
                       "Activate",
                       0,
                       "Cancel",
                       1,
                       "Input",
                       2,
                       "Menu",
                       3,
                       "DpadLeft",
                       4,
                       "DpadRight",
                       5,
                       "DpadUp",
                       6,
                       "DpadDown",
                       7,
                       "LStickLeft",
                       8,
                       "LStickRight",
                       9,
                       "LStickUp",
                       10,
                       "LStickDown",
                       11,
                       "FocusPrev",
                       12,
                       "FocusNext",
                       13,
                       "TweakSlow",
                       14,
                       "TweakFast",
                       15,
                       "KeyMenu_",
                       16,
                       "KeyLeft_",
                       17,
                       "KeyRight_",
                       18,
                       "KeyUp_",
                       19,
                       "KeyDown_",
                       20,
                       "COUNT",
                       21,
                       "InternalStart_",
                       ImGuiNavInput_LStickLeft);

        imgui.new_enum("SelectableFlags",
                       "None",
                       0,
                       "DontClosePopups",
                       1 << 0,
                       "SpanAllColumns",
                       1 << 1,
                       "AllowDoubleClick",
                       1 << 2,
                       "Disabled",
                       1 << 3);

        imgui.new_enum("StyleVar",
                       "Alpha",
                       0,
                       "WindowPadding",
                       1,
                       "WindowRounding",
                       2,
                       "WindowBorderSize",
                       3,
                       "WindowMinSize",
                       4,
                       "WindowTitleAlign",
                       5,
                       "ChildRounding",
                       6,
                       "ChildBorderSize",
                       7,
                       "PopupRounding",
                       8,
                       "PopupBorderSize",
                       9,
                       "FramePadding",
                       10,
                       "FrameRounding",
                       11,
                       "FrameBorderSize",
                       12,
                       "ItemSpacing",
                       13,
                       "ItemInnerSpacing",
                       14,
                       "IndentSpacing",
                       15,
                       "ScrollbarSize",
                       16,
                       "ScrollbarRounding",
                       17,
                       "GrabMinSize",
                       18,
                       "GrabRounding",
                       19,
                       "TabRounding",
                       20,
                       "ButtonTextAlign",
                       21,
                       "SelectableTextAlign",
                       22,
                       "COUNT",
                       23);

        imgui.new_enum("TabBarFlags",
                       "None",
                       0,
                       "Reorderable",
                       1 << 0,
                       "AutoSelectNewTabs",
                       1 << 1,
                       "TabListPopupButton",
                       1 << 2,
                       "NoCloseWithMiddleMouseButton",
                       1 << 3,
                       "NoTabListScrollingButtons",
                       1 << 4,
                       "NoTooltip",
                       1 << 5,
                       "FittingPolicyResizeDown",
                       1 << 6,
                       "FittingPolicyScroll",
                       1 << 7,
                       "FittingPolicyMask_",
                       ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll,
                       "FittingPolicyDefault_",
                       ImGuiTabBarFlags_FittingPolicyResizeDown);

        imgui.new_enum("TabItemFlags",
                       "None",
                       0,
                       "UnsavedDocument",
                       1 << 0,
                       "SetSelected",
                       1 << 1,
                       "NoCloseWithMiddleMouseButton",
                       1 << 2,
                       "NoPushId",
                       1 << 3);

        imgui.new_enum("TreeNodeFlags",
                       "None",
                       0,
                       "Selected",
                       1 << 0,
                       "Framed",
                       1 << 1,
                       "AllowItemOverlap",
                       1 << 2,
                       "NoTreePushOnOpen",
                       1 << 3,
                       "NoAutoOpenOnLog",
                       1 << 4,
                       "DefaultOpen",
                       1 << 5,
                       "OpenOnDoubleClick",
                       1 << 6,
                       "OpenOnArrow",
                       1 << 7,
                       "Leaf",
                       1 << 8,
                       "Bullet",
                       1 << 9,
                       "FramePadding",
                       1 << 10,
                       "NavLeftJumpsBackHere",
                       1 << 13,
                       "CollapsingHeader",
                       ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog);

        imgui.new_enum("WindowFlags",
                       "None",
                       0,
                       "NoTitleBar",
                       1 << 0,
                       "NoResize",
                       1 << 1,
                       "NoMove",
                       1 << 2,
                       "NoScrollbar",
                       1 << 3,
                       "NoScrollWithMouse",
                       1 << 4,
                       "NoCollapse",
                       1 << 5,
                       "AlwaysAutoResize",
                       1 << 6,
                       "NoBackground",
                       1 << 7,
                       "NoSavedSettings",
                       1 << 8,
                       "NoMouseInputs",
                       1 << 9,
                       "MenuBar",
                       1 << 10,
                       "HorizontalScrollbar",
                       1 << 11,
                       "NoFocusOnAppearing",
                       1 << 12,
                       "NoBringToFrontOnFocus",
                       1 << 13,
                       "AlwaysVerticalScrollbar",
                       1 << 14,
                       "AlwaysHorizontalScrollbar",
                       1 << 15,
                       "AlwaysUseWindowPadding",
                       1 << 16,
                       "NoNavInputs",
                       1 << 18,
                       "NoNavFocus",
                       1 << 19,
                       "UnsavedDocument",
                       1 << 20,
                       "NoNav",
                       ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
                       "NoDecoration",
                       ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar
                           | ImGuiWindowFlags_NoCollapse,
                       "NoInputs",
                       ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
                       "NavFlattened",
                       1 << 23,
                       "ChildWindow",
                       1 << 24,
                       "Tooltip",
                       1 << 25,
                       "Popup",
                       1 << 26,
                       "Modal",
                       1 << 27,
                       "ChildMenu",
                       1 << 28);

        // some flags that are useful but live in the internal imgui for now as their api will most
        // likely change.
        imgui.new_enum("ItemFlags",
                       "NoTabStop",
                       1 << 0,
                       "ButtonRepeat",
                       1 << 1,
                       "Disabled",
                       1 << 2,
                       "NoNav",
                       1 << 3,
                       "NoNavDefaultFocus",
                       1 << 4,
                       "SelectableDontClosePopup",
                       1 << 5,
                       "Default",
                       0);

        imgui.new_usertype<ImVec2>("ImVec2",
                                   sol::constructors<ImVec2(float, float)>(),
                                   "x", &ImVec2::x,
                                   "y", &ImVec2::y);

        //@TODO: Put a lot more stuff in here
        imgui.new_usertype<ImGuiIO>("IO",
                                    "new",
                                    sol::no_constructor,
                                    "configFlags",
                                    &ImGuiIO::ConfigFlags,
                                    "backendFlags",
                                    &ImGuiIO::BackendFlags,
                                    "displaySize",
                                    &ImGuiIO::DisplaySize,
                                    "deltaTime",
                                    &ImGuiIO::DeltaTime,
                                    "iniSavingRate",
                                    &ImGuiIO::IniSavingRate);

        imgui["getIO"]       = ImGui::GetIO;
        imgui["getStyle"]    = ImGui::GetStyle;
        imgui["newFrame"]    = ImGui::NewFrame;
        imgui["endFrame"]    = ImGui::EndFrame;
        imgui["render"]      = ImGui::Render;
        imgui["getDrawData"] = ImGui::GetDrawData;

        imgui["showDemoWindow"] = []()
        {
            bool bShow;
            ImGui::ShowDemoWindow(&bShow);
            return bShow;
        };
        imgui["showAboutWindow"] = []()
        {
            bool bShow;
            ImGui::ShowAboutWindow(&bShow);
            return bShow;
        };
        imgui["showMetricsWindow"] = []()
        {
            bool bShow;
            ImGui::ShowMetricsWindow(&bShow);
            return bShow;
        };
        imgui["showStyleEditor"]  = sol::overload(ImGui::ShowStyleEditor, []()
                                                  { ImGui::ShowStyleEditor(); });
        imgui["showStyleEditor"]  = ImGui::ShowStyleSelector;
        imgui["showFontSelector"] = ImGui::ShowFontSelector;
        imgui["showUserGuid"]     = ImGui::ShowUserGuide;
        imgui["getVersion"]       = ImGui::GetVersion;

        imgui["styleColorsDark"]    = sol::overload(ImGui::StyleColorsDark, []()
                                                    { ImGui::StyleColorsDark(); });
        imgui["styleColorsClassic"] = sol::overload(ImGui::StyleColorsClassic, []()
                                                    { ImGui::StyleColorsClassic(); });
        imgui["styleColorsLight"]   = sol::overload(ImGui::StyleColorsLight, []()
                                                    { ImGui::StyleColorsLight(); });

        imgui["beginWindow"]         = sol::overload([](const char* _str)
                                             { return ImGui::Begin(_str); },
                                             [](const char* _str, ImGuiWindowFlags _flags)
                                             { return ImGui::Begin(_str, NULL, _flags); });
        imgui["beginWindowClosable"] = sol::overload(
            [](const char* _str, sol::function _cb)
            {
                bool bOpen = true;
                if(ImGui::Begin(_str, &bOpen, 0))
                    _cb(bOpen);
            },
            [](const char* _str, ImGuiWindowFlags _flags, sol::function _cb)
            {
                bool bOpen = true;
                if(ImGui::Begin(_str, &bOpen, _flags))
                    _cb(bOpen);
            });

        imgui["endWindow"]  = ImGui::End;
        imgui["beginChild"] = sol::overload((bool (*)(const char*, const ImVec2&, bool, ImGuiWindowFlags))ImGui::BeginChild,
                                            [](const char* _str)
                                            { return ImGui::BeginChild(_str); },
                                            [](const char* _str, const ImVec2& _size)
                                            { return ImGui::BeginChild(_str, _size); },
                                            [](const char* _str, const ImVec2& _size, bool _border)
                                            { return ImGui::BeginChild(_str, _size, _border); });
        imgui["endChild"]   = ImGui::EndChild;

        imgui["isWindowAppearing"] = ImGui::IsWindowAppearing;
        imgui["isWindowCollapsed"] = ImGui::IsWindowCollapsed;
        imgui["isWindowFocused"]   = sol::overload(ImGui::IsWindowFocused, []()
                                                   { return ImGui::IsWindowFocused(); });
        imgui["isWindowHovered"]   = sol::overload(ImGui::IsWindowHovered, []()
                                                   { return ImGui::IsWindowHovered(); });

        imgui["getWindowPos"]               = ImGui::GetWindowPos;
        imgui["getWindowSize"]              = ImGui::GetWindowSize;
        imgui["getWindowWidth"]             = ImGui::GetWindowWidth;
        imgui["getWindowHeight"]            = ImGui::GetWindowHeight;
        imgui["getContentRegionMax"]        = ImGui::GetContentRegionMax;
        imgui["getContentRegionAvail"]      = ImGui::GetContentRegionAvail;
        imgui["getContentRegionAvailWidth"] = ImGui::GetContentRegionAvail;
        imgui["getWindowContentRegionMin"]  = ImGui::GetWindowContentRegionMin;
        imgui["getWindowContentRegionMax"]  = ImGui::GetWindowContentRegionMax;
        imgui["getWindowContentRegionMin"]  = ImGui::GetWindowContentRegionMin;
        imgui["getWindowContentRegionMax"]  = ImGui::GetWindowContentRegionMax;

        imgui["setNextWindowPos"] = sol::overload(
            ImGui::SetNextWindowPos,
            [](const ImVec2& _pos)
            { ImGui::SetNextWindowPos(_pos); },
            [](const ImVec2& _pos, ImGuiCond _cond)
            { ImGui::SetNextWindowPos(_pos, _cond); });
        imgui["setNextWindowSize"] = sol::overload(ImGui::SetNextWindowSize, [](const ImVec2& _size)
                                                   { ImGui::SetNextWindowSize(_size); });
        // imgui["setNextWindowSizeConstraints"] =
        //     sol::overload(ImGui::SetNextWindowSizeConstraints,
        //                   [](const ImVec2 & _size_min, const ImVec2 & _size_max) {
        //                       ImGui::SetNextWindowSizeConstraints(_size_min, _size_max);
        //                   });
        imgui["setNextWindowContentSize"] = ImGui::SetNextWindowContentSize;
        imgui["setNextWindowCollapsed"]   = sol::overload(
            ImGui::SetNextWindowCollapsed, [](bool _collapsed)
            { ImGui::SetNextWindowCollapsed(_collapsed); });
        imgui["setNextWindowFocus"]   = ImGui::SetNextWindowFocus;
        imgui["setNextWindowBgAlpha"] = ImGui::SetNextWindowBgAlpha;

        imgui["setWindowCollapsed"] = sol::overload((void (*)(bool, ImGuiCond))ImGui::SetWindowCollapsed,
                                                    [](bool _collapsed)
                                                    { ImGui::SetWindowCollapsed(_collapsed); },
                                                    (void (*)(const char*, bool, ImGuiCond))ImGui::SetWindowCollapsed,
                                                    [](const char* _name, bool _collapsed)
                                                    { ImGui::SetWindowCollapsed(_name, _collapsed); });
        imgui["setWindowFocus"]     = sol::overload((void (*)(const char*))ImGui::SetWindowFocus, (void (*)())ImGui::SetWindowFocus);
        imgui["setWindowFontScale"] = ImGui::SetWindowFontScale;
        imgui["setWindowPos"]       = sol::overload((void (*)(const ImVec2&, ImGuiCond))ImGui::SetWindowPos,
                                                    [](const ImVec2& _pos)
                                                    { ImGui::SetWindowPos(_pos); },
                                                    (void (*)(const char*, const ImVec2&, ImGuiCond))ImGui::SetWindowPos,
                                                    [](const char* _name, const ImVec2& _pos)
                                                    { ImGui::SetWindowPos(_name, _pos); });
        imgui["setWindowSize"]      = sol::overload((void (*)(const ImVec2&, ImGuiCond))ImGui::SetWindowSize,
                                                    [](const ImVec2& _size)
                                                    { ImGui::SetWindowSize(_size); },
                                                    (void (*)(const char*, const ImVec2&, ImGuiCond))ImGui::SetWindowSize,
                                                    [](const char* _name, const ImVec2& _size)
                                                    { ImGui::SetWindowSize(_name, _size); });
        imgui["setWindowCollapsed"] = sol::overload((void (*)(bool, ImGuiCond))ImGui::SetWindowCollapsed,
                                                    [](bool _collapsed)
                                                    { ImGui::SetWindowCollapsed(_collapsed); },
                                                    (void (*)(const char*, bool, ImGuiCond))ImGui::SetWindowCollapsed,
                                                    [](const char* _name, bool _collapsed)
                                                    { ImGui::SetWindowCollapsed(_name, _collapsed); });
        imgui["setWindowFocus"]     = sol::overload((void (*)())ImGui::SetWindowFocus, (void (*)(const char*))ImGui::SetWindowFocus);

        imgui["getScrollX"]        = ImGui::GetScrollX;
        imgui["getScrollY"]        = ImGui::GetScrollY;
        imgui["getScrollMaxX"]     = ImGui::GetScrollMaxX;
        imgui["getScrollMaxY"]     = ImGui::GetScrollMaxY;
        imgui["getScrollX"]        = ImGui::SetScrollX;
        imgui["getScrollY"]        = ImGui::SetScrollY;
        imgui["setScrollHereY"]    = ImGui::SetScrollHereY;
        imgui["setScrollFromPosY"] = ImGui::SetScrollFromPosY;

        imgui["pushFont"]       = ImGui::PushFont;
        imgui["popFont"]        = ImGui::PopFont;
        imgui["pushStyleColor"] = sol::overload(
            (void (*)(ImGuiCol, ImU32))ImGui::PushStyleColor, (void (*)(ImGuiCol, const ImVec4&))ImGui::PushStyleColor);
        imgui["popStyleColor"]          = sol::overload(ImGui::PopStyleColor, []()
                                                        { ImGui::PopStyleColor(); });
        imgui["pushStyleVar"]           = sol::overload((void (*)(ImGuiStyleVar, float))ImGui::PushStyleVar,
                                                        (void (*)(ImGuiStyleVar, const ImVec2&))ImGui::PushStyleVar);
        imgui["popStyleVar"]            = sol::overload(ImGui::PopStyleVar, []()
                                                        { ImGui::PopStyleVar(); });
        imgui["getStyleColorVec4"]      = ImGui::GetStyleColorVec4;
        imgui["getFont"]                = ImGui::GetFont;
        imgui["getFontSize"]            = ImGui::GetFontSize;
        imgui["getFontTexUvWhitePixel"] = ImGui::GetFontTexUvWhitePixel;

        imgui["pushItemWidth"]    = ImGui::PushItemWidth;
        imgui["popItemWidth"]     = ImGui::PopItemWidth;
        imgui["calcItemWidth"]    = ImGui::CalcItemWidth;
        imgui["pushTextWrapPos"]  = sol::overload(ImGui::PushTextWrapPos, []()
                                                  { ImGui::PushTextWrapPos(); });
        imgui["popTextWrapPos"]   = ImGui::PopTextWrapPos;
        imgui["pushButtonRepeat"] = ImGui::PushButtonRepeat;
        imgui["popButtonRepeat"]  = ImGui::PopButtonRepeat;

        imgui["separator"] = ImGui::Separator;
        imgui["sameLine"]  = sol::overload(
            ImGui::SameLine, []()
            { ImGui::SameLine(); },
            [](float _localPos)
            { ImGui::SameLine(_localPos); });
        imgui["newLine"]                      = ImGui::NewLine;
        imgui["spacing"]                      = ImGui::Spacing;
        imgui["dummy"]                        = ImGui::Dummy;
        imgui["indent"]                       = sol::overload(ImGui::Indent, []()
                                                              { ImGui::Indent(); });
        imgui["unindent"]                     = sol::overload(ImGui::Unindent, []()
                                                              { ImGui::Unindent(); });
        imgui["beginGroup"]                   = ImGui::BeginGroup;
        imgui["endGroup"]                     = ImGui::EndGroup;
        imgui["getCursorPos"]                 = ImGui::GetCursorPos;
        imgui["getCursorPosX"]                = ImGui::GetCursorPosX;
        imgui["getCursorPosY"]                = ImGui::GetCursorPosY;
        imgui["setCursorPos"]                 = ImGui::SetCursorPos;
        imgui["setCursorPosX"]                = ImGui::SetCursorPosX;
        imgui["setCursorPosY"]                = ImGui::SetCursorPosY;
        imgui["getCursorStartPos"]            = ImGui::GetCursorStartPos;
        imgui["getCursorScreenPos"]           = ImGui::GetCursorScreenPos;
        imgui["setCursorScreenPos"]           = ImGui::SetCursorScreenPos;
        imgui["alignTextToFramePadding"]      = ImGui::AlignTextToFramePadding;
        imgui["getTextLineHeight"]            = ImGui::GetTextLineHeight;
        imgui["getTextLineHeightWithSpacing"] = ImGui::GetTextLineHeightWithSpacing;
        imgui["getFrameHeight"]               = ImGui::GetFrameHeight;
        imgui["getFrameHeightWithSpacing"]    = ImGui::GetFrameHeightWithSpacing;

        imgui["pushID"] = sol::overload((void (*)(const char*))ImGui::PushID, (void (*)(int))ImGui::PushID);
        imgui["popID"]  = ImGui::PopID;
        imgui["getID"]  = (ImGuiID (*)(const char*))ImGui::GetID;

        imgui["text"] = [](const char* _text)
        {
            ImGui::TextUnformatted(_text);
        };
        imgui["textColored"] = [](const ImVec4& col, const char* _text)
        {
            ImGui::TextColored(col, "%s", _text);
        };
        imgui["textDisabled"] = [](const char* _text)
        {
            ImGui::TextDisabled("%s", _text);
        };
        imgui["textWrapped"] = [](const char* _text)
        {
            ImGui::TextWrapped("%s", _text);
        };
        imgui["labelText"] = [](const char* _label, const char* _text)
        {
            ImGui::LabelText(_label, "%s", _text);
        };
        imgui["bulletText"] = [](const char* _text)
        {
            ImGui::BulletText("%s", _text);
        };

        imgui["button"]          = sol::overload(ImGui::Button, [](const char* _label)
                                                 { return ImGui::Button(_label); });
        imgui["smallButton"]     = ImGui::SmallButton;
        imgui["invisibleButton"] = ImGui::InvisibleButton;
        imgui["arrowButton"]     = ImGui::ArrowButton;
        // Image
        // ImageButton
        imgui["checkbox"] = [](const char* _name, bool _bSelected, sol::function _cb)
        {
            if(ImGui::Checkbox(_name, &_bSelected))
            {
                _cb(_bSelected);
            }
        };
        imgui["radioButton"] = (bool (*)(const char*, bool))ImGui::RadioButton;
        imgui["progressBar"] = sol::overload(
            ImGui::ProgressBar,
            [](float _fraction)
            { ImGui::ProgressBar(_fraction); },
            [](float _fraction, const ImVec2& _size_arg)
            { ImGui::ProgressBar(_fraction, _size_arg); });
        imgui["bullet"] = ImGui::Bullet;

        imgui["beginCombo"] = sol::overload(ImGui::BeginCombo,
                                            [](const char* _label, const char* _preview_value)
                                            { return ImGui::BeginCombo(_label, _preview_value); });
        imgui["endCombo"]   = ImGui::EndCombo;

        /*     imgui["dragFloat"] = sol::overload(
            [](const char* _label, float _currentValue, sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue))
                    _cb(_currentValue);
            },
            [](const char* _label, float _currentValue, float _v_speed, sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue, _v_speed))
                    _cb(_currentValue);
            },
            [](const char* _label, float _currentValue, float _v_speed, float _v_min, sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue, _v_speed, _v_min))
                    _cb(_currentValue);
            },
            [](const char* _label, float _currentValue, float _v_speed, float _v_min, float _v_max, sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue, _v_speed, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                float _currentValue,
                float _v_speed,
                float _v_min,
                float _v_max,
                const char* _fmt,
                sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue, _v_speed, _v_min, _v_max, _fmt))
                    _cb(_currentValue);
            },
            [](const char* _label,
                float _currentValue,
                float _v_speed,
                float _v_min,
                float _v_max,
                const char* _fmt,
                sol::function _cb)
            {
                if(ImGui::DragFloat(_label, &_currentValue, _v_speed, _v_min, _v_max, _fmt))
                    _cb(_currentValue);
            });

        imgui["dragInt"] = sol::overload(
            [](const char* _label, int _currentValue, sol::function _cb)
            {
                if(ImGui::DragInt(_label, &_currentValue))
                    _cb(_currentValue);
            },
            [](const char* _label, int _currentValue, float _v_speed, sol::function _cb)
            {
                if(ImGui::DragInt(_label, &_currentValue, _v_speed))
                    _cb(_currentValue);
            },
            [](const char* _label, int _currentValue, float _v_speed, int _v_min, sol::function _cb)
            {
                if(ImGui::DragInt(_label, &_currentValue, _v_speed, _v_min))
                    _cb(_currentValue);
            },
            [](const char* _label, int _currentValue, float _v_speed, int _v_min, int _v_max, sol::function _cb)
            {
                if(ImGui::DragInt(_label, &_currentValue, _v_speed, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                int _currentValue,
                float _v_speed,
                int _v_min,
                int _v_max,
                const char* _fmt,
                sol::function _cb)
            {
                if(ImGui::DragInt(_label, &_currentValue, _v_speed, _v_min, _v_max, _fmt))
                    _cb(_currentValue);
            });

        imgui["sliderFloat"] = sol::overload(
            [](const char* _label, float _currentValue, float _v_min, float _v_max, sol::function _cb)
            {
                if(ImGui::SliderFloat(_label, &_currentValue, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                float _currentValue,
                float _v_min,
                float _v_max,
                const char* _format,
                sol::function _cb)
            {
                if(ImGui::SliderFloat(_label, &_currentValue, _v_min, _v_max, _format))
                    _cb(_currentValue);
            });

        imgui["sliderAngle"] = sol::overload(
            [](const char* _label, float _currentValue, sol::function _cb)
            {
                if(ImGui::SliderAngle(_label, &_currentValue))
                    _cb(_currentValue);
            },
            [](const char* _label, float _currentValue, float _v_degrees_min, sol::function _cb)
            {
                if(ImGui::SliderAngle(_label, &_currentValue, _v_degrees_min))
                    _cb(_currentValue);
            },
            [](const char* _label, float _currentValue, float _v_degrees_min, float _v_degrees_max, sol::function _cb)
            {
                if(ImGui::SliderAngle(_label, &_currentValue, _v_degrees_min, _v_degrees_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                float _currentValue,
                float _v_degrees_min,
                float _v_degrees_max,
                const char* _format,
                sol::function _cb)
            {
                if(ImGui::SliderAngle(_label, &_currentValue, _v_degrees_min, _v_degrees_max, _format))
                    _cb(_currentValue);
            });

        imgui["sliderInt"] = sol::overload(
            [](const char* _label, int _currentValue, int _v_min, int _v_max, sol::function _cb)
            {
                if(ImGui::SliderInt(_label, &_currentValue, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label, int _currentValue, int _v_min, int _v_max, const char* _format, sol::function _cb)
            {
                if(ImGui::SliderInt(_label, &_currentValue, _v_min, _v_max, _format))
                    _cb(_currentValue);
            });

        imgui["vSliderFloat"] = sol::overload(
            [](const char* _label,
                const ImVec2& _size,
                float _currentValue,
                float _v_min,
                float _v_max,
                sol::function _cb)
            {
                if(ImGui::VSliderFloat(_label, _size, &_currentValue, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                const ImVec2& _size,
                float _currentValue,
                float _v_min,
                float _v_max,
                const char* _format,
                sol::function _cb)
            {
                if(ImGui::VSliderFloat(_label, _size, &_currentValue, _v_min, _v_max, _format))
                    _cb(_currentValue);
            });

        imgui["vSliderInt"] = sol::overload(
            [](const char* _label, const ImVec2& _size, int _currentValue, int _v_min, int _v_max, sol::function _cb)
            {
                if(ImGui::VSliderInt(_label, _size, &_currentValue, _v_min, _v_max))
                    _cb(_currentValue);
            },
            [](const char* _label,
                const ImVec2& _size,
                int _currentValue,
                int _v_min,
                int _v_max,
                const char* _format,
                sol::function _cb)
            {
                if(ImGui::VSliderInt(_label, _size, &_currentValue, _v_min, _v_max, _format))
                    _cb(_currentValue);
            });*/

        //@TODO: add overloads
        // imgui["inputText"] = [](const char * _label, int _capacity, sol::function _cb) {
        //    //@TODO: This is kinda gnarly
        //    static stick::HashMap<const char *, stick::std::string> s_stringStorage;
        //    auto it = s_stringStorage.find(_label);
        //    stick::std::string * str;
        //    if (it != s_stringStorage.end())
        //        str = &it->value;
        //    else
        //    {
        //        auto res = s_stringStorage.insert(_label, std::string());
        //        str = &res.iterator->value;
        //    }

        //    str->reserve(_capacity);
        //    if (ImGui::InputText(_label, &(*str)[0], str->capacity()))
        //        _cb(str->cString());
        //};
        // imgui["inputTextMultiline"] = [](const char * _label, int _capacity, sol::function _cb) {
        //    //@TODO: This is kinda gnarly
        //    static stick::HashMap<const char *, stick::std::string> s_stringStorage;
        //    auto it = s_stringStorage.find(_label);
        //    stick::std::string * str;
        //    if (it != s_stringStorage.end())
        //        str = &it->value;
        //    else
        //    {
        //        auto res = s_stringStorage.insert(_label, std::string());
        //        str = &res.iterator->value;
        //    }

        //    str->reserve(_capacity);
        //    if (ImGui::InputTextMultiline(_label, &(*str)[0], str->capacity()))
        //        _cb(str->cString());
        //};

        imgui["inputFloat"] = sol::overload(
            [](const char* _label, float _current, sol::function _cb)
            {
                if(ImGui::InputFloat(_label, &_current))
                    _cb(_current);
            },
            [](const char* _label, float _current, float _step, sol::function _cb)
            {
                if(ImGui::InputFloat(_label, &_current, _step))
                    _cb(_current);
            },
            [](const char* _label, float _current, float _step, float _stepFast, sol::function _cb)
            {
                if(ImGui::InputFloat(_label, &_current, _step, _stepFast))
                    _cb(_current);
            },
            [](const char* _label, float _current, float _step, float _stepFast, const char* _fmt, sol::function _cb)
            {
                if(ImGui::InputFloat(_label, &_current, _step, _stepFast, _fmt))
                    _cb(_current);
            },
            [](const char* _label,
               float _current,
               float _step,
               float _stepFast,
               const char* _fmt,
               ImGuiInputTextFlags _flags,
               sol::function _cb)
            {
                if(ImGui::InputFloat(_label, &_current, _step, _stepFast, _fmt, _flags))
                    _cb(_current);
            });

        imgui["inputInt"] = sol::overload(
            [](const char* _label, int _current, sol::function _cb)
            {
                if(ImGui::InputInt(_label, &_current))
                    _cb(_current);
            },
            [](const char* _label, int _current, int _step, sol::function _cb)
            {
                if(ImGui::InputInt(_label, &_current, _step))
                    _cb(_current);
            },
            [](const char* _label, int _current, int _step, int _stepFast, sol::function _cb)
            {
                if(ImGui::InputInt(_label, &_current, _step, _stepFast))
                    _cb(_current);
            },
            [](const char* _label, int _current, int _step, int _stepFast, ImGuiInputTextFlags _flags, sol::function _cb)
            {
                if(ImGui::InputInt(_label, &_current, _step, _stepFast, _flags))
                    _cb(_current);
            });

        //@TODO: Overload
        imgui["colourEdit3"] = [](const char* _label, float _r, float _g, float _b, sol::function _cb)
        {
            float tmp[3] = { _r, _g, _b };
            if(ImGui::ColorEdit3(_label, tmp))
                _cb(tmp[0], tmp[1], tmp[2]);
        };
        imgui["colourEdit4"] = sol::overload(
            [](const char* _label, float _r, float _g, float _b, float _a, sol::function _cb)
            {
                float tmp[4] = { _r, _g, _b, _a };
                if(ImGui::ColorEdit4(_label, tmp))
                    _cb(tmp[0], tmp[1], tmp[2], tmp[3]);
            },
            [](const char* _label, float _r, float _g, float _b, float _a, ImGuiColorEditFlags _flags, sol::function _cb)
            {
                float tmp[4] = { _r, _g, _b, _a };
                if(ImGui::ColorEdit4(_label, tmp, _flags))
                    _cb(tmp[0], tmp[1], tmp[2], tmp[3]);
            });
        //@TODO: Overload
        imgui["colourPicker3"] = [](const char* _label, float _r, float _g, float _b, sol::function _cb)
        {
            float tmp[3] = { _r, _g, _b };
            if(ImGui::ColorPicker3(_label, tmp))
                _cb(tmp[0], tmp[1], tmp[2]);
        };
        //@TODO: Overload
        imgui["colourPicker3"] = [](const char* _label, float _r, float _g, float _b, float _a, sol::function _cb)
        {
            float tmp[4] = { _r, _g, _b, _a };
            if(ImGui::ColorPicker4(_label, tmp))
                _cb(tmp[0], tmp[1], tmp[2], tmp[3]);
        };
        //@TODO: Overload
        imgui["colourButton"] = [](const char* _label, float _r, float _g, float _b, float _a, sol::function _cb)
        {
            ImVec4 tmp = { _r, _g, _b, _a };
            if(ImGui::ColorButton(_label, tmp))
                _cb(tmp.x, tmp.y, tmp.z, tmp.y);
        };

        imgui["setColorEditOptions"] = ImGui::SetColorEditOptions;

        imgui["treeNode"]                  = (bool (*)(const char*))ImGui::TreeNode;
        imgui["treeNodeEx"]                = sol::overload((bool (*)(const char*, ImGuiTreeNodeFlags))ImGui::TreeNodeEx,
                                                           [](const char* _label)
                                                           { return ImGui::TreeNodeEx(_label); });
        imgui["treePush"]                  = (void (*)(const char*))ImGui::TreePush;
        imgui["treePop"]                   = ImGui::TreePop;
        imgui["getTreeNodeToLabelSpacing"] = ImGui::GetTreeNodeToLabelSpacing;
        imgui["collapsingHeader"]          = sol::overload((bool (*)(const char*, ImGuiTreeNodeFlags))ImGui::CollapsingHeader,
                                                           [](const char* _label)
                                                           { ImGui::CollapsingHeader(_label); });
        //@TODO: Overloads
        imgui["collapsingHeaderClosable"] = sol::overload([](const char* _label, sol::function _cb)
                                                          {
                bool bOpen = true;
                ImGui::CollapsingHeader(_label, &bOpen);
                _cb(bOpen); });

        imgui["selectable"] = sol::overload(
            [](const char* _label, bool _bSelected, sol::function _cb)
            {
                if(ImGui::Selectable(_label, &_bSelected))
                    _cb(_bSelected);
            },
            [](const char* _label, bool _bSelected, ImGuiSelectableFlags _flags, sol::function _cb)
            {
                if(ImGui::Selectable(_label, &_bSelected, _flags))
                    _cb(_bSelected);
            });

        // PlotLines

        imgui["value"] = sol::overload((void (*)(const char*, bool))ImGui::Value,
                                       (void (*)(const char*, int))ImGui::Value,
                                       (void (*)(const char*, float, const char*))ImGui::Value,
                                       [](const char* _pref, float _val)
                                       { ImGui::Value(_pref, _val); });

        imgui["beginMainMenuBar"] = ImGui::BeginMainMenuBar;
        imgui["endMainMenuBar"]   = ImGui::EndMainMenuBar;
        imgui["beginMenuBar"]     = ImGui::BeginMenuBar;
        imgui["endMenuBar"]       = ImGui::EndMenuBar;
        imgui["beginMenu"]        = sol::overload(ImGui::BeginMenu, [](const char* _label)
                                                  { return ImGui::BeginMenu(_label); });
        imgui["endMenu"]          = ImGui::EndMenu;
        imgui["menuItem"]         = sol::overload((bool (*)(const char*, const char*, bool, bool))ImGui::MenuItem,
                                                  [](const char* _label)
                                                  { return ImGui::MenuItem(_label); },
                                                  [](const char* _label, const char* _shortcut)
                                                  { return ImGui::MenuItem(_label, _shortcut); },
                                                  [](const char* _label, const char* _shortcut, bool _selected)
                                                  {
                                              return ImGui::MenuItem(_label, _shortcut, _selected);
                                          });

        imgui["beginTooltip"] = ImGui::BeginTooltip;
        imgui["endTooltip"]   = ImGui::EndTooltip;
        imgui["setTooltip"]   = [](const char* _txt)
        {
            ImGui::SetTooltip("%s", _txt);
        };

        // imgui["openPopup"] = ImGui::OpenPopup;
        imgui["beginPopup"]            = sol::overload(ImGui::BeginPopup, [](const char* _str)
                                                       { return ImGui::BeginPopup(_str); });
        imgui["beginPopupContextItem"] = sol::overload(
            ImGui::BeginPopupContextItem,
            [](const char* _str)
            { return ImGui::BeginPopupContextItem(_str); },
            []()
            { return ImGui::BeginPopupContextItem(); });
        imgui["beginPopupContextWindow"] = sol::overload(
            ImGui::BeginPopupContextWindow,
            [](const char* _str)
            { return ImGui::BeginPopupContextWindow(_str); },
            [](const char* _str, int _mouse_button)
            { return ImGui::BeginPopupContextWindow(_str, _mouse_button); },
            []()
            { return ImGui::BeginPopupContextWindow(); });

        imgui["beginPopupContextVoid"] = sol::overload(
            ImGui::BeginPopupContextVoid,
            [](const char* _str)
            { return ImGui::BeginPopupContextVoid(_str); },
            []()
            { return ImGui::BeginPopupContextVoid(); });
        imgui["beginPopupModal"] = sol::overload(
            [](const char* _name, sol::function _cb)
            {
                if(ImGui::BeginPopupModal(_name, NULL))
                    _cb();
            },
            [](const char* _name, ImGuiWindowFlags _flags, sol::function _cb)
            {
                if(ImGui::BeginPopupModal(_name, NULL, _flags))
                    _cb();
            });
        imgui["endPopup"]             = ImGui::EndPopup;
        imgui["openPopupOnItemClick"] = sol::overload(
            ImGui::OpenPopupOnItemClick, [](const char* _name)
            { return ImGui::OpenPopupOnItemClick(_name); });
        imgui["isPopupOpen"]       = (bool (*)(const char*))ImGui::IsPopupOpen;
        imgui["closeCurrentPopup"] = ImGui::CloseCurrentPopup;

        imgui["columns"] = sol::overload(
            ImGui::Columns,
            [](int _c)
            { ImGui::Columns(_c); },
            [](int _c, const char* _id)
            { ImGui::Columns(_c, _id); },
            [](int _c, const char* _id, bool _bBorder)
            { ImGui::Columns(_c, _id, _bBorder); });
        imgui["nextColumn"]      = ImGui::NextColumn;
        imgui["endPopup"]        = ImGui::EndPopup;
        imgui["GetColumnIndex"]  = ImGui::GetColumnIndex;
        imgui["GetColumnWidth"]  = sol::overload(ImGui::GetColumnWidth, []()
                                                 { return ImGui::GetColumnWidth(); });
        imgui["setColumnWidth"]  = ImGui::SetColumnWidth;
        imgui["GetColumnOffset"] = sol::overload(ImGui::GetColumnOffset, []()
                                                 { return ImGui::GetColumnOffset(); });
        imgui["setColumnOffset"] = ImGui::SetColumnOffset;
        imgui["GetColumnsCount"] = ImGui::GetColumnsCount;

        imgui["beginTabBar"]  = sol::overload(ImGui::BeginTabBar, [](const char* _id)
                                              { return ImGui::BeginTabBar(_id); });
        imgui["endTabBar"]    = ImGui::EndTabBar;
        imgui["beginTabItem"] = sol::overload(
            [](const char* _name, sol::function _cb)
            {
                bool bOpen = true;
                if(ImGui::BeginTabItem(_name, &bOpen))
                    _cb(bOpen);
            },
            [](const char* _name, ImGuiTabItemFlags _flags, sol::function _cb)
            {
                bool bOpen = true;
                if(ImGui::BeginTabItem(_name, &bOpen, _flags))
                    _cb(bOpen);
            });
        imgui["endTabItem"]       = ImGui::EndTabItem;
        imgui["setTabItemClosed"] = ImGui::SetTabItemClosed;

        imgui["beginDragDropSource"] = sol::overload(ImGui::BeginDragDropSource, []()
                                                     { return ImGui::BeginDragDropSource(); });
        imgui["setDragDropPayload"]  = [](const char* _name, const sol::object& _obj)
        {
            static sol::object s_obj;
            s_obj            = _obj;
            sol::object* ptr = &s_obj;
            return ImGui::SetDragDropPayload(_name, &ptr, sizeof(ptr));
        };

        imgui["test"] = [](const sol::object& _obj, sol::this_state _s)
        {
            sol::state_view view(_s);
            printf("typename %s\n", sol::type_name(_s, _obj.get_type()).c_str());
            if(_obj.get_type() == sol::type::userdata)
            {
                int c = _obj.push();
                printf("usertype: %s\n", sol::associated_type_name(_s, -1, _obj.get_type()).c_str());
                lua_pop(_s, c);
            }
        };
        imgui["endDragDropSource"]   = ImGui::EndDragDropSource;
        imgui["beginDragDropTarget"] = ImGui::BeginDragDropTarget;
        //@TODO: expose ImGuiPayload
        // imgui["acceptDragDropPayload"] = sol::overload(ImGui::AcceptDragDropPayload, [](const char *
        // _str) { return ImGui::AcceptDragDropPayload(_str); });
        imgui["acceptDragDropPayload"] = [](const char* _name, sol::function _cb, sol::this_state _s)
        {
            if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(_name))
            {
                ASSERT(payload->DataSize == sizeof(sol::object*), "Incorect Payload");
                const sol::object* obj = (*(const sol::object**)payload->Data);
                _cb(*obj);
            }
        };
        // imgui["endDragDropTarget"] = ImGui::EndDragDropTarget;
        // imgui["getDragDropPayload"] = ImGui::GetDragDropPayload;

        // imgui["pushClipRect"] = ImGui::PushClipRect;
        // imgui["popClipRect"] = ImGui::PopClipRect;

        // imgui["setItemDefaultFocus"] = ImGui::SetItemDefaultFocus;
        // imgui["setKeyboardFocusHere"] = ImGui::SetKeyboardFocusHere;

        // imgui["isItemHovered"] = sol::overload(ImGui::IsItemHovered, []()
        //     { return ImGui::IsItemHovered(); });
        // imgui["isItemActive"] = ImGui::IsItemActive;
        // imgui["isItemFocused"] = ImGui::IsItemFocused;
        // imgui["isItemClicked"] = sol::overload(ImGui::IsItemClicked, []()
        //     { return ImGui::IsItemClicked(); });
        // imgui["isItemVisible"] = ImGui::IsItemVisible;
        // imgui["isItemEdited"] = ImGui::IsItemEdited;
        // imgui["isItemActivated"] = ImGui::IsItemActivated;
        // imgui["isItemDeactivated"] = ImGui::IsItemDeactivated;
        // imgui["isItemDeactivatedAfterEdit"] = ImGui::IsItemDeactivatedAfterEdit;
        // imgui["isAnyItemHovered"] = ImGui::IsAnyItemHovered;
        // imgui["isAnyItemActive"] = ImGui::IsAnyItemActive;
        // imgui["isAnyItemFocused"] = ImGui::IsAnyItemFocused;
        // imgui["getItemRectMin"] = ImGui::GetItemRectMin;
        // imgui["getItemRectMax"] = ImGui::GetItemRectMax;
        // imgui["getItemRectSize"] = ImGui::GetItemRectSize;
        // imgui["setItemAllowOverlap"] = ImGui::SetItemAllowOverlap;

        // imgui["getKeyIndex"] = ImGui::GetKeyIndex;
        // imgui["isKeyDown"] = ImGui::IsKeyDown;
        // imgui["isKeyPressed"] = ImGui::IsKeyPressed;
        // imgui["isKeyReleased"] = ImGui::IsKeyReleased;
        // imgui["getKeyPressedAmount"] = ImGui::GetKeyPressedAmount;
        // imgui["isMouseDown"] = ImGui::IsMouseDown;
        // imgui["isAnyMouseDown"] = ImGui::IsAnyMouseDown;
        // imgui["isMouseClicked"] = ImGui::IsMouseClicked;
        // imgui["isMouseDoubleClicked"] = ImGui::IsMouseDoubleClicked;
        // imgui["isMouseReleased"] = ImGui::IsMouseReleased;
        // imgui["isMouseDragging"] = ImGui::IsMouseDragging;
        // imgui["isMouseHoveringRect"] = ImGui::IsMouseHoveringRect;
        // imgui["getMousePos"] = ImGui::GetMousePos;
        // imgui["getMousePosOnOpeningCurrentPopup"] = ImGui::GetMousePosOnOpeningCurrentPopup;
        // imgui["getMouseDragDelta"] = ImGui::GetMouseDragDelta;
        // imgui["resetMouseDragDelta"] = ImGui::ResetMouseDragDelta;
        // imgui["getMouseCursor"] = ImGui::GetMouseCursor;
        // imgui["setMouseCursor"] = ImGui::SetMouseCursor;
        // imgui["captureKeyboardFromApp"] = ImGui::CaptureKeyboardFromApp;
        // imgui["captureMouseFromApp"] = ImGui::CaptureMouseFromApp;
    }
}

#else
void Lumos::BindImGuiLua(sol::state& solState) { }
#endif
